/**
 * @file factapprsc.c
 * @brief Factory Method for Application Resources.
 *
 * Come specificato dal pattern Factory Methods in questo sorgente si vuole
 * fornire la possibilità di richiamare delle attività (o meglio dei metodi)
 * per avviare in un determinato modo l'utilizzo delle risorse.
 * In particolare il sorgente è stato pensato per gestire le risorse applicative.
 *
 * @date Mar 3, 2012
 * @author Francesco Corvino
 */
#include "factapprsc.h"
#include "../logproxy/logproxy.h"

void FactApp_initManagedRsc( DescApplication* initvalue){
	SingleApp_initialize(initvalue);
}

/**
 * @brief Richiesta gestita dal sistema.
 *
 * I client che richiedono la risorsa tramite questa invocazione devono attendere
 * che il sistema liberi la risorsa.
 * Questo comporta che le richieste concorrenziali non verranno gestite
 * secondo policy di priorità ma saranno trattate direttamente dal sistema.
 * D'altro canto essendo il sistema a gestirle avranno più probabilità a essere
 * effettuate prima rispetto alle richieste gestite dall'applicativo.
 *
 * @param operation l'operazione da eseguire sulle risorse.
 * @see FactApp_getApplicationAccess() richiesta gestita dall'applicativo seguendo le priorità.
 */
int FactApp_getSystemAccess(SingApp_OperationCunc operation){
	return SingleApp_getResource(operation);
}

/**
 * @brief Richiesta gestita dall'applicativo.
 *
 * @param operation l'operazione da eseguire sulle risorse.
 * @see FactApp_getSystemAccess() richiesta gestita dal sistema.
 */
int FactApp_getApplicationAccess(SingApp_OperationCunc operation){
	//TODOH implementare la struttura a chain per la gestione delle richieste lato applicativo
	return SingleApp_getResource(operation);
}


/**
 * @brief Cerca un comando tra quelli registrati.
 *
 * @param name nome del comando da ricercare.
 * @param regcommands registro dei comandi.
 */
DescCommand * _utilityop_findCmd(DynArray* regcommands, char* name){
	DescCommand icom;
	memcpy(icom.name,name,strlen(name));
	simplelog(getMultipleStrCat("cerco il comando:", icom.name, NULL));
	void *res = getElementFromDynArray(regcommands,&icom);
    return (DescCommand*) res;
}

/**
 * @brief Funzione pubblica inserita per permettere l'utilizzo più agevole dei comandi.
 *
 * @param name Nome del comando da cercare.
 * @see _utilityop_findCmd() funzione richiamata per cercare i comandi.
 */
DescCommand * FactApp_getCommand(char*name){
	DescCommand *ret = NULL;
	int op(DescApplication*da) {
		ret = _utilityop_findCmd(&da->commands, name);
		return 0;
	};
	FactApp_getSystemAccess(op);
	return ret;
}

/**
 * @brief Aggiunge un comando al registro dei comandi.
 *
 * Funzione di inizializzazione e di aggiornamento runtime del programma.
 * Permette di modificare la lista dei comandi conosciuti registrando quello passato.
 *
 * @param cmd puntatore al comando da aggiungere in memoria
 */
int FactApp_addCommand(DescCommand *cmd){
	int op(DescApplication *app) {
		return addElementToDynArray(&(app->commands),cmd);
	}
	return FactApp_getSystemAccess(op);
}

/**
 * @brief Aggiunge una richiesta al registro.
 *
 * La funzione utilizza la coda di sistema per eseguire l'operazione.
 */
int FactApp_addRequest(DescRequest *req){
	int op(DescApplication *app) {
		return addElementToDynArray(&(app->requests),req);
	}
	return FactApp_getSystemAccess(op);
}

void FactApp_terminateAll(){
	int op(DescApplication *app) {
		//TODOH liberare tutte le risorse prima di terminare.
		return 0;
	}
	int ret = FactApp_getSystemAccess(op);
	exit(ret);
}
